#include "app_bt.h"
#include <string.h>
#include "log/log.h"
#include <unistd.h>
#include "app_serial.h"

static char bt_data[1024];
static int bt_data_len = 0;
static char fix_header[2] = {0xf1, 0xdd};

static int wait_data(int fd)
{
    // 等待数据到来(50ms)
    usleep(1000 * 50);

    // 读取数据
    char data[4];
    read(fd, data, 4);
    if (memcmp(data, "OK\r\n", 4) != 0)
    {
        log_error("等待ACK超时");
        return -1;
    }
    return 0;
}

/**
 * @brief 判断蓝牙是否连接成功
 *
 * @param device 设备信息
 * @return int 0:成功 -1:失败
 */
int app_bt_is_connected(Device_t *device)
{
    // 向蓝牙文件写入数据
    char *cmd = "AT\r\n";
    write(device->fd, cmd, strlen(cmd));

    // 等待蓝牙返回数据
    return wait_data(device->fd);
}

/**
 * @brief 重启蓝牙模块
 *
 * @param device 设备信息
 * @return int 0:成功 -1:失败
 */
int app_bt_reset(Device_t *device)
{
    // 向蓝牙文件写入数据
    char *cmd = "AT+RESET\r\n";
    write(device->fd, cmd, strlen(cmd));

    // 等待蓝牙返回数据
    return wait_data(device->fd);
}

/**
 * @brief 设置蓝牙名称
 *
 * @param device 设备信息
 * @param name 蓝牙名称
 * @return int 0:成功 -1:失败
 */
int app_bt_set_name(Device_t *device, char *name)
{
    // 向蓝牙文件写入数据
    char cmd[30];
    sprintf(cmd, "AT+NAME%s\r\n", name);
    write(device->fd, cmd, strlen(cmd));

    // 等待蓝牙返回数据
    return wait_data(device->fd);
}

/**
 * @brief 设置蓝牙波特率
 *
 * @param device 设备信息
 * @param baudrate 波特率
 * @return int 0:成功 -1:失败
 */
int app_bt_set_baudrate(Device_t *device, BT_BR_t baudrate)
{
    // 向蓝牙文件写入数据
    char cmd[30];
    sprintf(cmd, "AT+BAUD%c\r\n", baudrate);
    write(device->fd, cmd, strlen(cmd));

    // 等待蓝牙返回数据
    return wait_data(device->fd);
}

/**
 * @brief 设置蓝牙组网ID
 *
 * @param device 设备信息
 * @param netid 组网ID
 * @return int 0:成功 -1:失败
 */
int app_bt_set_netid(Device_t *device, char *netid)
{
    // 向蓝牙文件写入数据
    char cmd[30];
    sprintf(cmd, "AT+NETID%s\r\n", netid);
    write(device->fd, cmd, strlen(cmd));

    // 等待蓝牙返回数据
    return wait_data(device->fd);
}

/**
 * @brief 设置蓝牙MAC地址
 *
 * @param device 设备信息
 * @param mac MAC地址
 * @return int 0:成功 -1:失败
 */
int app_bt_set_mac(Device_t *device, char *mac)
{
    // 向蓝牙文件写入数据
    char cmd[30];
    sprintf(cmd, "AT+MADDR%s\r\n", mac);
    write(device->fd, cmd, strlen(cmd));

    // 等待蓝牙返回数据
    return wait_data(device->fd);
}

// 初始化蓝牙模块
static int app_bt_init_bt(Device_t *device)
{
    // 初始化串口模块
    if (app_serial_init(device) != 0)
    {
        return -1;
    }

    // 将串口设置为非阻塞模式
    if (app_serial_setBlock(device, 0) != 0)
    {
        return -1;
    }

    // 重启串口
    if (app_serial_flush(device) != 0)
    {
        log_error("刷新串口缓冲区失败");
        return -1;
    }

    // 判断连接是否成功，如果蓝牙连接成功，则蓝牙波特率为9600
    if (app_bt_is_connected(device) == 0)
    {
        // 设置蓝牙名称
        if (app_bt_set_name(device, "gate-way") != 0)
        {
            log_error("设置蓝牙名称失败");
            return -1;
        }

        // 设置蓝牙波特率为115200
        if (app_bt_set_baudrate(device, BT_BR_115200) != 0)
        {
            log_error("设置蓝牙波特率失败");
            return -1;
        }

        // 重启蓝牙模块
        if (app_bt_reset(device) != 0)
        {
            log_error("重启蓝牙模块失败");
            return -1;
        }

        // 等待蓝牙重启
        sleep(2);
    }

    // 设置串口波特率为115200
    if (app_serial_setBaudRate(device, BR_115200) != 0)
    {
        return -1;
    }

    // 刷新串口缓冲区
    if (app_serial_flush(device) != 0)
    {
        log_error("刷新串口缓冲区失败");
        return -1;
    }

    // 判断是否连接成功
    if (app_bt_is_connected(device) != 0)
    {
        log_error("蓝牙初始化失败");
        return -1;
    }

    // 设置组网ID
    if (app_bt_set_netid(device, "8E9B") != 0)
    {
        log_error("设置组网ID失败");
        return -1;
    }

    // 设置MAC地址
    if (app_bt_set_mac(device, "0037") != 0)
    {
        log_error("设置MAC地址失败");
        return -1;
    }

    // 将串口设置为阻塞模式
    if (app_serial_setBlock(device, 1) != 0)
    {
        return -1;
    }

    // 刷新串口缓冲区
    if (app_serial_flush(device) != 0)
    {
        log_error("刷新串口缓冲区失败");
        return -1;
    }

    log_debug("蓝牙初始化成功");
    return 0;
}

/**
 * @brief 初始化蓝牙模块
 * 注册读后和写前回调函数
 * @param device 设备信息
 * @return int 0:成功 -1:失败
 */
int app_bt_init(Device_t *device)
{
    // 注册读后和写前回调函数
    device->post_read = post_read_bt;
    device->pre_write = pre_write_bt;

    // 初始化蓝牙模块
    if (app_bt_init_bt(device) != 0)
    {
        return -1;
    }

    return 0;
}

static void remove_data(int num)
{
    memmove(bt_data, bt_data + num, bt_data_len - num);
    bt_data_len -= num;
}

/*
 接收方得到数据（3 + [2]）：f1 dd 07 23 23 ff ff 41 42 43
    f1 dd : 固定的头部
    07： 之后数据的长度（5-16之间）
    23 23：对端（发送方）的MADDR
    ff ff: 我的MADDR或ffff(群发)
    41 42 43：发送的数据
处理后的数据格式：conn_type id_len msg_len id msg

1. 缓存所有读取到的数据(一次读不一定能读完)
2. 检查已缓存的数据里有没有一份完整的蓝牙数据
3. 如果还没有返回0, 继续读取处理
4. 如果有，根据它生成字符数组，保存到data中，并返回数据长度

*/
/**
 * @brief 读后回调函数
 *
 * @param data 数据
 * @param len  容量
 * @return int 实际读取的字节数
 */
int post_read_bt(char *data, int len)
{
    memcpy(bt_data + bt_data_len, data, len);
    bt_data_len += len;

    // 判断是否有完整的蓝牙数据
    if (bt_data_len < 8)
    {
        log_debug("蓝牙数据不完整,继续读取...1");
        return 0;
    }

    // -7是因为最低要求是8位数据才能组成一份完整的蓝牙数据
    for (int i = 0; i < bt_data_len - 7; i++)
    {
        // 找到固定的头部
        if (memcmp(fix_header, bt_data + i, 2) == 0)
        {
            // 覆盖前面的无效数据
            if (i > 0)
            {
                remove_data(i);
            }

            // 定义完整的蓝牙数据长度
            int data_len = 3 + bt_data[2];

            if (bt_data_len < data_len)
            {
                log_debug("蓝牙数据不完整,继续读取...2");
                return 0;
            }

            // 清零数据
            memset(data, 0, len);
            // 解析数据
            data[0] = 1;
            data[1] = 2;
            data[2] = bt_data[2] - 4;
            // id
            memcpy(data + 3, bt_data + 3, 2);
            // mes
            memcpy(data + 5, bt_data + 7, data[2]);

            // 清零缓存
            remove_data(data_len);

            return 5 + data[2];
        }
        if (i > 0)
        {
            remove_data(i);
        }
    }
    return 0;
}

/**
 * 处理将要写入蓝牙数据函数
 data: conn_type id_len msg_len id msg
 蓝牙发送数据格式例子：
    41 54 2b 4d 45 53 48 00 ff ff 61 62 63 0d 0a
    41 54 2b 4d 45 53 48 00： AT+MESH（固定头部, 8个字节）
    ff ff: 对端的MADDR（如果是FFFF代表群发）
    61 62 63: 要发送的数据（不超过12字节）
    0d 0a：/r/n（固定结尾）
 */
/**
 * @brief 写前回调函数
 *
 * @param data MQTT数据
 * @param len 实际写入的MQTT字节数
 * @param size 容量
 * @return int 实际写入的蓝牙字节数
 */
int pre_write_bt(char *data, int len, int size)
{
    // 判断写入的数据是否符合蓝牙模块的要求
    if (len < 6)
    {
        log_error("MQTT数据长度不完整");
        return -1;
    }

    int data_len = 12 + data[2];

    // 判断容量是否足够
    if (size < data_len)
    {
        log_error("写前数据容量不足");
        return -1;
    }

    char bt_data[data_len];

    // 解析数据
    // 固定头部
    memcpy(bt_data, "AT+MESH", 8);
    // 对端的MADDR
    memcpy(bt_data + 8, data + 3, 2);
    // 要发送的数据
    memcpy(bt_data + 10, data + 5, data[2]);
    // 固定结尾
    memcpy(bt_data + 10 + data[2], "\r\n", 2);

    // 清理数据
    memset(data, 0, size);
    // 写入数据
    memcpy(data, bt_data, data_len);

    return data_len;
}
